<?php

namespace Builder;


class Client
{
    /**
     * 构造器决定如何构造每一部分,指挥者决定构造哪些部分
     */
    public static function main()
    {
        $director = new Director(new BuilderOne());
        $product = $director->createMinimalProduct();
        $product->show();

        $director = new Director(new BuilderTwo());
        $product = $director->createMaximalProduct();
        $product->show();
    }
}

/**
 * 产品角色
 * Class Product
 * @package Builder
 */
class Product
{
    private string $partA;
    private string $partB;
    private string $partC;

    public function setPartA(string $partA): void
    {
        $this->partA = $partA;
    }

    public function setPartB(string $partB): void
    {
        $this->partB = $partB;
    }

    public function setPartC(string $partC): void
    {
        $this->partC = $partC;
    }

    public function show()
    {
        echo json_encode(array_filter(get_object_vars($this))), PHP_EOL;
    }
}

/**
 * 抽象构造器, 定义初始化和返回,由子类去决定如何构造
 * Class Builder
 * @package Builder
 */
abstract class Builder
{
    protected Product $product;

    public function __construct()
    {
        $this->product = new Product();
    }

    abstract public function builderPartA();
    abstract public function builderPartB();
    abstract public function builderPartC();

    public function getResult()
    {
        return $this->product;
    }
}

/**
 * 具体构造器1,按照自己的方法来实现各个部分的构造
 * Class BuilderOne
 * @package Builder
 */
class BuilderOne extends Builder
{

    public function builderPartA()
    {
        $this->product->setPartA('One');
    }

    public function builderPartB()
    {
        $this->product->setPartB('One');
    }

    public function builderPartC()
    {
        $this->product->setPartC('One');
    }
}

/**
 * 具体构造器2,按照自己的方法来实现各个部分的构造
 * Class BuilderTwo
 * @package Builder
 */
class BuilderTwo extends Builder
{

    public function builderPartA()
    {
        $this->product->setPartA('Two');
    }

    public function builderPartB()
    {
        $this->product->setPartB('Two');
    }

    public function builderPartC()
    {
        $this->product->setPartC('Two');
    }
}

/**
 * 指挥者, 决定构造哪些部分
 * Class Director
 * @package Builder
 */
class Director
{
    private Builder $builder;

    /**
     * @param Builder $builder
     */
    public function __construct(Builder $builder)
    {
        $this->builder = $builder;
    }

    /**
     * @return Product
     */
    public function createMinimalProduct(): Product
    {
        $this->builder->builderPartA();

        return $this->builder->getResult();
    }

    /**
     * @return Product
     */
    public function createMaximalProduct(): Product
    {
        $this->builder->builderPartA();
        $this->builder->builderPartB();
        $this->builder->builderPartC();

        return $this->builder->getResult();
    }
}

Client::main();
